﻿using System;
using System.Collections.Generic;
using System.IO;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage;
using Avalonia.Styling;
using AvaloniaEdit;
using AvaloniaEdit.Document;
using AvaloniaEdit.Folding;
using AvaloniaEdit.TextMate;
using FluentAvalonia.UI.Controls;
using TextMateSharp.Grammars;

namespace DevHub.WindowsApp.Pages.Code;

public partial class CodeEditorView : UserControl
{
    private List<Language> Languages { get; set; }
    private RegistryOptions RegistryOptions { get; }
    private TextMate.Installation TextMateInstallation { get; }
    private FoldingManager FoldingManager { get; set; }
    private XmlFoldingStrategy FoldingStrategy { get; set; } = new();

    public CodeEditorView()
    {
        InitializeComponent();
        ThemeBox.ItemsSource = Enum.GetValues<ThemeName>();
        var theme = Application.Current!.ActualThemeVariant == ThemeVariant.Light ? ThemeName.Light : ThemeName.Dark;
        ThemeBox.SelectedItem = theme;
        Editor.FontFamily = Avalonia.Media.FontFamily.Parse("Cascadia Code,Consolas,Menlo,Monospace");
        RegistryOptions = new RegistryOptions(theme);
        LangBox.ItemsSource = Languages = RegistryOptions.GetAvailableLanguages();
        TextMateInstallation = Editor.InstallTextMate(RegistryOptions);
        Editor.Document = new TextDocument();
        LangBox.SelectedItem = RegistryOptions.GetLanguageByExtension(".cs");
        TextMateInstallation.SetGrammar(RegistryOptions.GetScopeByExtension(".cs"));
        Editor.TextChanged += EditorTextChange;
        FoldingManager = FoldingManager.Install(Editor.TextArea);
        FoldingStrategy.UpdateFoldings(FoldingManager, Editor.Document);
    }

    private void EditorTextChange(object? sender, EventArgs e)
    {
        FoldingStrategy.UpdateFoldings(FoldingManager, Editor.Document);
    }

    private void InitializeComponent()
    {
        AvaloniaXamlLoader.Load(this);
        Editor = this.FindControl<TextEditor>("Editor");
        LangBox = this.FindControl<FAComboBox>("LangBox");
        ThemeBox = this.FindControl<FAComboBox>("ThemeBox");
    }

    private async void OpenFileClick(object? sender, RoutedEventArgs e)
    {
        var top = TopLevel.GetTopLevel(this);
        if (top == null) return;
        var resultList = await top.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions());
        if (resultList.Count == 0) return;
        var result = resultList[0];
        var reader = new StreamReader(await result.OpenReadAsync());
        Editor.Text = await reader.ReadToEndAsync();
        reader.Dispose();
        var s = RegistryOptions.GetLanguageByExtension(Path.GetExtension(result.Path.LocalPath));
        if(s == null)return;
        LangBox.SelectedItem = s;
    }

    private void ClearClick(object? sender, RoutedEventArgs e)
    {
        Editor.Text = "";
    }

    private void LangSelectionChanged(object? sender, SelectionChangedEventArgs e)
    {
        if(LangBox.SelectedItem is not Language s)return;
        TextMateInstallation.SetGrammar(RegistryOptions.GetScopeByLanguageId(s.Id));
    }

    private void ThemeSelectionChanged(object? sender, SelectionChangedEventArgs e)
    {
        var selected = (ThemeName)ThemeBox.SelectedItem!;
        if (RegistryOptions == null!) return;
        TextMateInstallation.SetTheme(RegistryOptions.LoadTheme(selected));
    }
}